package com.wdy.golden.tinysql.util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.util.ReflectionUtils;

public class ReflectionUtil extends ReflectionUtils {

	/**
	 * get the method of invoked class
	 * @param s
	 * @return
	 * @throws SecurityException 
	 * @throws NoSuchMethodException 
	 */
	public static Method getMethod(ProceedingJoinPoint jp) throws NoSuchMethodException, SecurityException{
		Signature s = jp.getSignature();
        MethodSignature ms = null;
        Method method = null;
        if (!(s instanceof MethodSignature)) {
            throw new IllegalArgumentException("[Tinysql] Error:Is not a MethodSignature instance!");
        }else{
	        ms = (MethodSignature) s;
	        Object target = jp.getTarget();
	        method = target.getClass().getMethod(ms.getName(), ms.getParameterTypes());
        }
        return method;
	}

	/**
	 * 
	 * @param returnClass
	 * @param instance
	 * @param methodName
	 * @param parameterTypes
	 * @param parameterValues
	 * @return
	 * @throws NoSuchMethodException
	 * @throws SecurityException
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 */
	@SuppressWarnings("unchecked")
	public static <T> T invokeMethod(Class<T> returnClass, String methodName, Object instance, Class<?>[] parameterTypes, Object[] parameterValues) 
			throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
		Method method = instance.getClass().getMethod(methodName, parameterTypes);
		return (T) method.invoke(instance,parameterValues);
	}

	public static <T> T invokeMethod(Class<T> returnClass, String methodName, Object instance) 
			throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
		return invokeMethod(returnClass,methodName,instance,new Class[0],new Object[0]);
	}
	
	
	/**
	 * 
	 * @param instance
	 * @param methodName
	 * @param parameterTypes
	 * @param methodArgs
	 * @throws NoSuchMethodException
	 * @throws SecurityException
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 */
	public static void invokeMethodReturnVoid(String methodName, Object instance, Class<?>[] parameterTypes, Object[] parameterValues) 
			throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
		Method method = instance.getClass().getMethod(methodName, parameterTypes);
		method.invoke(instance,parameterValues);
	}

	public static void invokeMethodReturnVoid(String methodName, Object instance) 
			throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
		invokeMethodReturnVoid(methodName,instance,new Class[0],new Object[0]);
	}
	
	/**
	 * 方法是否存在
	 * @param methodName
	 * @param clazz
	 * @param parameterTypes
	 * @return
	 */
	public static boolean existsMethod(String methodName, Class<?> clazz, Class<?>[] parameterTypes){		
		try {
			clazz.getMethod(methodName,parameterTypes);
		} catch (NoSuchMethodException e) {
			return false;
		} catch (SecurityException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	
	/**
	 * 方法是否不存在
	 * @param methodName
	 * @param clazz
	 * @param parameterTypes
	 * @return
	 */
	public static boolean notExistsMethod(String methodName, Class<?> clazz, Class<?>[] parameterTypes){	
		return !existsMethod(methodName, clazz, parameterTypes);
	}
	
	
	/**
	 * 方法是否存在
	 * @param methodName
	 * @param instance
	 * @return
	 */
	public static boolean existsMethod(String methodName, Class<?> clazz){
		return existsMethod(methodName,clazz,new Class[0]);
	}

	/**
	 * 方法是否不存在
	 * @param methodName
	 * @param instance
	 * @return
	 */
	public static boolean notExistsMethod(String methodName, Class<?> clazz){
		return !existsMethod(methodName,clazz,new Class[0]);
	}
}
